package com.xiyu.service.service.market;

import com.xiyu.service.framework.mail.service.BatchSendMailService;
import com.xiyu.service.model.system.user.SystemUser;
import com.xiyu.service.service.system.user.UserService;
import com.xiyu.service.vo.market.marketSetting.MarketSettingUpdateReplyInput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingCreateReplyInput;
import com.xiyu.service.model.market.setting.MarketSettingReply;
import com.xiyu.service.repository.market.setting.MarketSettingReplyRepository;
import com.xiyu.service.vo.market.marketSetting.MarketSettingSingleGetReplyOutput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingReplyListOutput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingReplyListInput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingUpdateSenderInput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingCreateSenderInput;
import com.xiyu.service.model.market.setting.MarketSettingSender;
import com.xiyu.service.repository.market.setting.MarketSettingSenderRepository;
import com.xiyu.service.vo.market.marketSetting.MarketSettingSingleGetSenderOutput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingSenderListOutput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingSenderListInput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingUpdateDomainInput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingCreateDomainInput;
import com.xiyu.service.model.market.setting.MarketSettingDomain;
import com.xiyu.service.repository.market.setting.MarketSettingDomainRepository;
import com.xiyu.service.vo.market.marketSetting.MarketSettingSingleGetDomainOutput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingDomainListOutput;
import com.xiyu.service.vo.market.marketSetting.MarketSettingDomainListInput;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.util.*;

import org.springframework.transaction.annotation.Transactional;

import com.xiyu.service.util.entity.EntityUtils;
import com.xiyu.service.convert.market.MarketSettingConvert;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.market.MarketSettingErrorCode.*;
import static com.xiyu.service.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

/**
 * 营销设置 Service 实现类
 */
@Service
@Validated
public class MarketSettingServiceImpl implements MarketSettingService {

    @Resource
    private MarketSettingReplyRepository marketSettingReplyRepository;

    @Resource
    private MarketSettingSenderRepository marketSettingSenderRepository;

    @Resource
    private MarketSettingDomainRepository marketSettingDomainRepository;

    @Resource
    private UserService userService;

    @Resource
    private BatchSendMailService batchSendMailService;




    @Override
    public List<MarketSettingDomainListOutput> domainList(MarketSettingDomainListInput inputVO) {
        return MarketSettingConvert.INSTANCE.domainListOutputConvert(marketSettingDomainRepository.listQuery(inputVO));
    }

    @Override
    public MarketSettingSingleGetDomainOutput singleGetDomain(Long id) {
        Optional<MarketSettingDomain> optionMarketSettingDomain = marketSettingDomainRepository.findById(id);
        if(optionMarketSettingDomain.isEmpty()){
            throw exception(MARKET_SETTING_DOMAIN_NOT_EXIST);
        }
        return MarketSettingConvert.INSTANCE.singleGetDomainOutputConvert(optionMarketSettingDomain.get());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createDomain(MarketSettingCreateDomainInput inputVO) {
        MarketSettingDomain existDomain = marketSettingDomainRepository.findByDomainName(inputVO.getDomainName()).orElse(null);
        if(existDomain != null){
            throw exception(MARKET_SETTING_DOMAIN_SAME);
        }
        MarketSettingDomain newMarketSettingDomain = MarketSettingConvert.INSTANCE.createDomainInputConvert(inputVO);
        newMarketSettingDomain = marketSettingDomainRepository.insert(newMarketSettingDomain);
        try {
           batchSendMailService.createWebHook(newMarketSettingDomain);
        } catch (Exception e) {
            throw exception(MARKET_SETTING_CREATE_WEBHOOK_ERROR, e.getMessage());
        }
        return newMarketSettingDomain.id();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateDomain(MarketSettingUpdateDomainInput inputVO) {
        MarketSettingDomain existDomain = marketSettingDomainRepository.findByDomainName(inputVO.getDomainName()).orElse(null);
        if(existDomain != null && existDomain.id() != inputVO.getId()){
            throw exception(MARKET_SETTING_DOMAIN_SAME);
        }
        Optional<MarketSettingDomain> optionalOldMarketSettingDomain = marketSettingDomainRepository.findById(inputVO.getId());
        if(optionalOldMarketSettingDomain.isEmpty()){
            throw exception(MARKET_SETTING_DOMAIN_NOT_EXIST);
        }
        MarketSettingDomain updateMarketSettingDomain = MarketSettingConvert.INSTANCE.updateDomainInputConvert(inputVO);
        if (!EntityUtils.isEquals(optionalOldMarketSettingDomain.get(), updateMarketSettingDomain))
            marketSettingDomainRepository.update(updateMarketSettingDomain);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deletedDomain(Long id) {
        Optional<MarketSettingDomain> optionalMarketSettingDomain = marketSettingDomainRepository.findById(id);
        if(optionalMarketSettingDomain.isEmpty()){
            throw exception(MARKET_SETTING_DOMAIN_NOT_EXIST);
        }
        marketSettingDomainRepository.deleteById(id);
        return true;
    }

    @Override
    public List<MarketSettingSenderListOutput> senderList(MarketSettingSenderListInput inputVO) {
        List<Long> ownerUserIds = userService.getOwnerUserIds(getLoginUserId());
        List<MarketSettingSender> senderList = marketSettingSenderRepository.listQuery(inputVO, ownerUserIds);
        return MarketSettingConvert.INSTANCE.senderListOutputConvert(senderList);
    }

    @Override
    public MarketSettingSingleGetSenderOutput singleGetSender(Long id) {
        Optional<MarketSettingSender> optionMarketSettingSender = marketSettingSenderRepository.findById(id);
        if(optionMarketSettingSender.isEmpty()){
            throw exception(MARKET_SETTING_SENDER_NOT_EXIST);
        }
        return MarketSettingConvert.INSTANCE.singleGetSenderOutputConvert(optionMarketSettingSender.get());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createSender(MarketSettingCreateSenderInput inputVO) {
        MarketSettingSender existsSender = marketSettingSenderRepository.findBySenderAddressAndDomainIdAndOwnerId(inputVO.getSenderAddress(), inputVO.getDomainId(), inputVO.getOwnerId()).orElse(null);
        if(existsSender != null){
            throw exception(MARKET_SETTING_SENDER_SAME);
        }
        MarketSettingSender newMarketSettingSender = MarketSettingConvert.INSTANCE.createSenderInputConvert(inputVO);
        newMarketSettingSender = marketSettingSenderRepository.insert(newMarketSettingSender);
        return newMarketSettingSender.id();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateSender(MarketSettingUpdateSenderInput inputVO) {
        MarketSettingSender existsSender = marketSettingSenderRepository.findBySenderAddressAndDomainIdAndOwnerId(inputVO.getSenderAddress(), inputVO.getDomainId(), inputVO.getOwnerId()).orElse(null);
        if(existsSender != null && existsSender.id() != inputVO.getId()){
            throw exception(MARKET_SETTING_SENDER_SAME);
        }
        Optional<MarketSettingSender> optionalOldMarketSettingSender = marketSettingSenderRepository.findById(inputVO.getId());
        if(optionalOldMarketSettingSender.isEmpty()){
            throw exception(MARKET_SETTING_SENDER_NOT_EXIST);
        }
        MarketSettingSender updateMarketSettingSender = MarketSettingConvert.INSTANCE.updateSenderInputConvert(inputVO);
        if (!EntityUtils.isEquals(optionalOldMarketSettingSender.get(), updateMarketSettingSender))
            marketSettingSenderRepository.update(updateMarketSettingSender);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deletedSender(Long id) {
        Optional<MarketSettingSender> optionalMarketSettingSender = marketSettingSenderRepository.findById(id);
        if(optionalMarketSettingSender.isEmpty()){
            throw exception(MARKET_SETTING_SENDER_NOT_EXIST);
        }
        marketSettingSenderRepository.deleteById(id);
        return true;
    }

    @Override
    public List<MarketSettingReplyListOutput> replyList(MarketSettingReplyListInput inputVO) {
        List<Long> ownerUserIds = userService.getOwnerUserIds(getLoginUserId());
        List<MarketSettingReply> replyList = marketSettingReplyRepository.listQuery(inputVO, ownerUserIds);
        return MarketSettingConvert.INSTANCE.replyListOutputConvert(replyList);
    }

    @Override
    public MarketSettingSingleGetReplyOutput singleGetReply(Long id) {
        Optional<MarketSettingReply> optionMarketSettingReply = marketSettingReplyRepository.findById(id);
        if(optionMarketSettingReply.isEmpty()){
            throw exception(MARKET_SETTING_REPLY_NOT_EXIST);
        }
        return MarketSettingConvert.INSTANCE.singleGetReplyOutputConvert(optionMarketSettingReply.get());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createReply(MarketSettingCreateReplyInput inputVO) {
        MarketSettingReply existReply = marketSettingReplyRepository.findByReplyAddressAndOwnerId(inputVO.getReplyAddress(), inputVO.getOwnerId()).orElse(null);
        if(existReply != null){
            throw exception(MARKET_SETTING_REPLY_SAME);
        }
        MarketSettingReply newMarketSettingReply = MarketSettingConvert.INSTANCE.createReplyInputConvert(inputVO);
        newMarketSettingReply = marketSettingReplyRepository.insert(newMarketSettingReply);
        return newMarketSettingReply.id();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateReply(MarketSettingUpdateReplyInput inputVO) {
        MarketSettingReply existReply = marketSettingReplyRepository.findByReplyAddressAndOwnerId(inputVO.getReplyAddress(), inputVO.getOwnerId()).orElse(null);
        if(existReply != null && existReply.id()  != inputVO.getId()){
            throw exception(MARKET_SETTING_REPLY_SAME);
        }
        Optional<MarketSettingReply> optionalOldMarketSettingReply = marketSettingReplyRepository.findById(inputVO.getId());
        if(optionalOldMarketSettingReply.isEmpty()){
            throw exception(MARKET_SETTING_REPLY_NOT_EXIST);
        }
        MarketSettingReply updateMarketSettingReply = MarketSettingConvert.INSTANCE.updateReplyInputConvert(inputVO);
        if (!EntityUtils.isEquals(optionalOldMarketSettingReply.get(), updateMarketSettingReply))
            marketSettingReplyRepository.update(updateMarketSettingReply);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deletedReply(Long id) {
        Optional<MarketSettingReply> optionalMarketSettingReply = marketSettingReplyRepository.findById(id);
        if(optionalMarketSettingReply.isEmpty()){
            throw exception(MARKET_SETTING_REPLY_NOT_EXIST);
        }
        marketSettingReplyRepository.deleteById(id);
        return true;
    }

}
